package com.zim.aliot.client;

import java.io.UnsupportedEncodingException;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import com.zim.aliot.config.LcxConfig;
import com.zim.aliot.config.TextJsonHttpMessageConverter;
import com.zim.aliot.lcx.LcxResult;
import lombok.extern.slf4j.Slf4j;

/**
 * 赖床讯客户端
 * @author zi-m.cn
 */
@Component
@Slf4j
public class LcxClient {
    
    private final RestTemplate restTemplate;
    
    public LcxClient(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
        restTemplate.getMessageConverters().add(new TextJsonHttpMessageConverter());
    }
    
    @Autowired
    private LcxConfig lcxConfig;
    
    /**
     * 车辆绑定
     * @param supplierNo
     * @param equipMentId
     * @param vin
     * @param carSn
     * @return
     */
    public LcxResult bandCars(int supplierNo,String equipMentId,String vin,String carSn) {
    	MultiValueMap<String,String > request = new LinkedMultiValueMap<String,String>();
    	request.add("supplier_no", String.valueOf(supplierNo));
    	request.add("equipment_id", equipMentId);
    	request.add("car_unique_id", vin);
    	request.add("license_plate", carSn);
    	request.add("bind_source", "iot");
    	
    	if(1376920002 == supplierNo) {
    		request.add("bluetooth_id", equipMentId.substring(7));
    	}
    	return request("bind_car", request);
    }
    
    /**
     * 车辆解绑
     * @param supplierNo
     * @param vin
     * @return
     */
    public LcxResult unBandCars(int supplierNo,String vin) {
    	MultiValueMap<String,String > request = new LinkedMultiValueMap<String,String>();
    	request.add("supplier_no", String.valueOf(supplierNo));
    	request.add("car_unique_id", vin);
    	return request("unbind_car", request);
    }
    
    public LcxResult sendEvent(String vin,String event,String action,long event_time,long send_time) {
        MultiValueMap<String,String > request = new LinkedMultiValueMap<String,String>();
        request.add("car_unique_id", vin);
        request.add("event", event);
        request.add("action", action);
        request.add("event_time",String.valueOf(event_time));
        request.add("send_time", String.valueOf(send_time));
        return request("send_car_event", request);
          
    }
    
    /**
     * 通知指令执行结果
     * @param seq_id
     * @param command_result
     * @param complete_time
     * @param reason
     * @return
     */
    public LcxResult acceptInform(String seq_id,boolean command_result,long complete_time,String reason) {
    	MultiValueMap<String,String > request = new LinkedMultiValueMap<String,String>();
        request.add("seq_id", seq_id);
        request.add("command_result", command_result?"0":"1");
        request.add("complete_time",String.valueOf(complete_time));
        request.add("reason", reason);
        return request("command_result", request);	
    }
    
    /**
     * 车辆告警
     * @param car_unique_id
     * @param type
     * @param warning
     * @param warning_time
     * @param send_time
     * @return
     */
    public LcxResult sendWarning(String vin,String type,String warning,long warning_time,long send_time) {
    	MultiValueMap<String,String > request = new LinkedMultiValueMap<String,String>();
        request.add("car_unique_id", vin);
        request.add("type", type);
        request.add("warning",warning);
        request.add("warning_time", String.valueOf(warning_time));
        request.add("send_time", String.valueOf(send_time));
		return request("send_car_warning", request);
    	
    }
    
    /**
     * 蓝牙密码通知
     * @param result
     * @param vin
     * @param pwd
     * @param success_time
     * @return
     */
    public LcxResult acceptBlueTooth(boolean result,String vin,String pwd,long success_time) {
    	MultiValueMap<String,String > request = new LinkedMultiValueMap<String,String>();
        request.add("result", result?"0":"1");
        request.add("car_unique_id", vin);
        request.add("pwd", pwd);
        request.add("success_time", String.valueOf(success_time));
		return request("bluetooth_pwd_update_result", request);
    }
    
    /**
     * 拍照事件通知	
     * @param seq_id
     * @param photo
     * @param longitude
     * @param latitude
     * @param take_time
     * @return
     */
    public LcxResult sendPhotoEvent(String seq_id,String photo,String longitude,String latitude,long take_time) {
    	MultiValueMap<String,String > request = new LinkedMultiValueMap<String,String>();
        request.add("seq_id", seq_id);
        request.add("photo", photo);
        request.add("longitude", longitude);
        request.add("latitude", latitude);
        request.add("take_time", String.valueOf(take_time));
    	return request("send_take_photo_event", request);
    }
    
    public <T> LcxResult request(String path, MultiValueMap<String, String> request) {
        
        try { 
            ResponseEntity<LcxResult> result = restTemplate.postForEntity(lcxConfig.getClientUrl() + path,new HttpEntity<>(request,headers()),LcxResult.class);
            if(result.getStatusCodeValue()==200) {  
                return result.getBody();
            }else {
                log.error("[lcx访问返回]:{}",result.getStatusCode());
                return null;
            }
        } catch (RestClientException e) {
            log.error("[lcx客户端异常]:{}",e.getMessage());
           return null;
        }
    }
    
    
    protected HttpHeaders headers() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        
        String timeStamp = String.valueOf(System.currentTimeMillis());
        String seqId = createSeqId();
        String sign = createSign(lcxConfig.getLocalUsername(),lcxConfig.getLocalKey(),lcxConfig.getLocalIp(),seqId, timeStamp);
        
        headers.add("User-Name", lcxConfig.getLocalUsername());
        headers.add("Ip", lcxConfig.getLocalIp());
        headers.add("Time-Stamp",timeStamp);
        headers.add("Seq-Id", seqId);
        headers.add("Sign", sign);
        
        return headers;
    }
 
        
    protected String createSeqId() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replaceAll("-", "");
    }
    
    /**
     * 生成签名，
     * @param seqId
     * @param timeStamp
     * @return
     */
    protected  String createSign(String userName,String key ,String ip,String seqId, String timeStamp) {
        //第一步：对参数按照key=value的格式，并按照参数名ASCII字典序排序如下
        //第二步：拼接API密钥
        String sign = "user_name=" + userName
                + "&ip=" + ip
                + "&time_stamp=" + timeStamp
                + "&seq_id=" + seqId
                + "&key=" + key;
        //第三部：md5加密，并转化为大写
        try {
            return DigestUtils.md5DigestAsHex(sign.getBytes("UTF-8")).toUpperCase();
        } catch (UnsupportedEncodingException e) {
            log.error("[MD5]:{}",e.getMessage());
            return null;
        }
      
    }

}
